package com.hrt.datasender.process.heartbeat;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import com.btcode.common.MyLog;
import com.btcode.log.ILog;
import com.btcode.reflect.AutoClassLoader;
import com.btcode.reflect.IClassFinder;
import com.btcode.reflect.IClassLoader;
import com.hrt.datasender.datadao.model.BcSendPlatformDataStrategyModel;
import com.hrt.datasender.datadao.model.BcSendPlatformModel;
import com.hrt.datasender.datadao.service.BcSendPlatformDataStrategyService;
import com.hrt.datasender.datadao.service.BcSendPlatformService;

public final class HeartbeatLoader {

    private String basePacket = "com.hrt.datasender.process.heartbeat";

    private ILog log;

    private static volatile HeartbeatLoader instance;

    /**
     * 程序中存在的策略
     */
    private List<IHeartbeat> existHeartbeats = new ArrayList<>();

    private HashMap<String, IHeartbeat> heartbeatsMap = new HashMap<>();

    private HeartbeatLoader() {
        log = MyLog.getInstance().getLogger(getClass().getName());
    }

    public static HeartbeatLoader getInstance() {
        if (instance == null) {
            synchronized (HeartbeatLoader.class) {
                if (instance == null) {
                    instance = new HeartbeatLoader();
                }
            }
        }
        return instance;
    }

    public IHeartbeat getHeartbeatByPlatformId(String platformId) {

        try {
            initHeartbeatsMap();
        } 
        catch (Exception e) {
            log.error("初始化心跳策略失败", e);
            return null;
        }

        IHeartbeat strategy = heartbeatsMap.get(platformId);
        return strategy;
    }

    private synchronized void initHeartbeatsMap() throws Exception {

        if (!heartbeatsMap.isEmpty()) {
            return;
        }

        List<BcSendPlatformModel> platforms = BcSendPlatformService.getInstance().getModelList();
        List<IHeartbeat> heartbeats = getExistHeartbeats();

        for (BcSendPlatformModel platform : platforms) {
            String heartbeatId = platform.getHeartbeatStrategyId();

            for (IHeartbeat heartbeat : heartbeats) {

                if (heartbeat.getHeartbeatId().equals(heartbeatId)) {
                    try {
                        IHeartbeat heartbeatInstance = heartbeat.getClass().newInstance();
                        heartbeatsMap.put(platform.getPlatformId(), heartbeatInstance);
                        log.info("平台：" + platform.getPlatformId() + "的心跳：" + heartbeatId + "已加载");
                    } 
                    catch (Exception e) {
                        log.error("加载出错，平台：" + platform.getPlatformId() + "的心跳：" + heartbeatId);
                    }

                }
            }
        }
    }

    /**
     * 获取系统中存在的策略
     * 
     * @param packetName
     * @return
     * @throws IOException
     * @throws ClassNotFoundException
     * @throws InstantiationException
     * @throws IllegalAccessException
     */
    public synchronized List<IHeartbeat> getExistHeartbeats()
            throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException {

        if (existHeartbeats != null && existHeartbeats.size() > 0) {
            return existHeartbeats;
        }

        IClassFinder heartbeatFinder = new HeartbeatClassFinder();
        IClassLoader calssLoader = new AutoClassLoader(heartbeatFinder);

        List<IHeartbeat> heartbeatList = new ArrayList<>();
        List<Class<?>> classes = calssLoader.loadClass(getClass(), basePacket);

        for (Class<?> myClass : classes) {
            Object instance = myClass.newInstance();
            heartbeatList.add((IHeartbeat) instance);
        }

        existHeartbeats = heartbeatList;

        return heartbeatList;
    }

    /**
     * 获取配置好的，平台策略id集合
     * 
     * @return
     */
    public Set<String> getPlatformStrategySet() {

        List<BcSendPlatformModel> platformModels = BcSendPlatformService.getInstance().getModelList();

        Set<String> platformSet = new HashSet<>();

        for (BcSendPlatformModel platform : platformModels) {

            String platformId = platform.getPlatformId();
            List<BcSendPlatformDataStrategyModel> strategys = BcSendPlatformDataStrategyService.getInstance()
                    .getList(platformId);

            for (BcSendPlatformDataStrategyModel strategy : strategys) {
                String strategyId = strategy.getStorageStrategyId();
                platformSet.add(strategyId);
            }

        }

        return platformSet;
    }
}
